<?php
/**
 * bs多规格sku商城系统
 * ============================================================================
 * 版权所有 2024-2099 wltx666.com，并保留所有权利。
 * 网站地址: https://wltx666.com
 * ============================================================================
 * Author: 草上飞
 * Email: wltx@alipay168.cn
 * QQ: 2719875001
 * Date: 2025/2/24
 * 描述: 聊天事件处理类，包含聊天相关的事件处理逻辑
 */

/**
 * 用于检测业务代码死循环或者长时间阻塞等问题
 * 如果发现业务卡死，可以将下面declare打开（去掉//注释），并执行php start.php reload
 * 然后观察一段时间workerman.log看是否有process_timeout异常
 */
#declare(ticks=1);

namespace app\events;

// 修改了之后要重启一下服务！！！！！
use app\result\admin\AdminResult;
use app\result\chat\WorkerResult;
use app\result\UploadResult;
use app\result\UserResult;
use app\service\ChatWorkerService;
use GatewayClient\Gateway;
use Workerman\Timer;

class ChatEvents
{
    /**
     * 当Worker启动时执行的操作
     * @param object $worker Worker对象
     */
    public static function onWorkerStart($worker)
    {
        bs_log('onWorkerStart', 'onWorkerStart', 'worker.log');
        ChatWorkerService::init_gateway();

        // 每30秒执行一次数据库心跳检测
        Timer::add(30, function () use ($worker) {
            try {
                cache('abc'); // 防止redis断线
                $db = \think\facade\Db::connect();
                $db->query('select 1');
                bs_log(1, 'success数据库心跳检测', 'worker.log');
            } catch (\Exception $e) {
                bs_log($e->getMessage(), 'error数据库心跳检测', 'worker.log');
            }
        });
    }

    /**
     * 当WebSocket连接建立时执行的操作
     * @param string $client_id 客户端ID
     * @param mixed $data 连接数据
     */
    public static function onWebSocketConnect($client_id, $data)
    {
        bs_log(['client_id' => $client_id, 'data' => $data], 'onWebSocketConnect', 'worker.log');
        // ChatLog::add([$client_id, $data], 'onWebSocketConnect', 1);
    }

    /**
     * 当客户端连接建立时执行的操作
     * @param string $client_id 客户端ID
     */
    public static function onConnect($client_id)
    {
        bs_log($client_id, 'onConnect', 'worker.log');
        echo '开始连接： ' . $client_id, PHP_EOL;
        // var_dump($client_id);
    }

    /**
     * 当Worker停止时执行的操作
     * @param object $businessWorker Worker对象
     */
    public static function onWorkerStop($businessWorker)
    {
        bs_log('做一些清理工作，例如保存一些重要数据等', 'onWorkerStop', 'worker.log');
        // 清除所有客户端
        // echo '$businessWorker';
    }

    /**
     * 发送登录过期消息给客户端
     * @param string $client_id 客户端ID
     */
    private static function need_login($client_id)
    {
        $pushMsg = [
            'type' => 'text',
            'content' => '您登录已过期，请重新登录',
        ];
        Gateway::sendToClient($client_id, self::toJson($pushMsg));
    }

    /**
     * 当接收到客户端消息时执行的操作
     * @param string $client_id 客户端ID
     * @param mixed $message 客户端消息
     * @return void|bool
     */
    public static function onMessage($client_id, $message)
    {
        bs_log(PHP_EOL . PHP_EOL . PHP_EOL . PHP_EOL . PHP_EOL . PHP_EOL, date('Y-m-d H:i:s'), 'worker.log');
        bs_log(['client_id' => $client_id, 'message' => $message], 'onMessage', 'worker.log');

        $messageData = @json_decode($message, true);
        if (!$messageData) {
            return;
        }
        // bs_log($messageData, '解密数据', 'worker.log');

        switch ($messageData['type']) {
            case 'ping':
                Gateway::sendToClient($client_id, self::toJson([
                    'type' => 'pong'
                ]));
                return;
            case 'login':
                self::handleLogin($client_id, $messageData);
                break;
            case 'login-kefu':
                self::handleLoginKefu($client_id, $messageData);
                break;
            case 'listen-msg':
                self::handleListenMsg($client_id, $messageData);
                break;
            case 'text':
            case 'image':
            case 'file':
            case 'goods':
            case 'order':
                self::handleChat($client_id, $messageData);
                break;
        }
    }

    /**
     * 处理聊天消息
     * @param string $client_id 客户端ID
     * @param array $messageData 消息数据
     */
    public static function handleChat($client_id, $messageData)
    {
        $user = $_SESSION['chat_user'];

        if (empty($user)) {
            self::need_login($client_id);
            return;
        }
        bs_log($user, '发送的用户' . __LINE__, 'worker.log');

        $to_id = $user['to_id'] ?? 0;
        $messageData['user_id'] = $user['user_id'];
        $messageData['to_id'] = $to_id;
        bs_log($messageData, '发送来的消息' . __LINE__, 'worker.log');

        $msgType = $messageData['type'];
        if ($msgType == 'goods') {
            $messageData['content'] = json_encode($messageData['goods_info'], JSON_UNESCAPED_UNICODE);
        } elseif ($msgType == 'order') {
            $messageData['content'] = json_encode($messageData['order_info'], JSON_UNESCAPED_UNICODE);
        }

        // 添加消息记录
        $res = (new WorkerResult())->add_message($messageData);
        if ($res['code'] !== 0) {
            Gateway::sendToClient($client_id, self::toJson([
                'type' => 'text',
                'content' => '网络异常，请确保聊天网络正常',
            ]));
            return;
        }

        $pushMsg = [
            'type' => $messageData['type'],
            'content' => $messageData['content'],
        ];

        if ($msgType == 'image' || $msgType == 'file') {
            $fileInfo = UploadResult::get_file_info($messageData['content']);
            $pushMsg['file_info'] = $fileInfo;
        }

        // 发送给对方
        $pushMsg['isSelf'] = false;

        if ($to_id <> $user['user_id']) {
            $toClientID = Gateway::getClientIdByUid($to_id);
            bs_log($toClientID, '发送给用户' . __LINE__, 'worker.log');
            Gateway::sendToUid($to_id, self::toJson($pushMsg));
        }
    }

    /**
     * 处理客服登录逻辑
     * @param string $client_id 客户端ID
     * @param array $data 登录数据
     */
    private static function handleLoginKefu($client_id, $data)
    {
        $targetUser = $data['targetUser'] ?? [];
        if (!$targetUser) {
            Gateway::sendToClient($client_id, self::toJson([
                'type' => 'error',
                'msg' => '请选择目标用户',
            ]));
            return;
        }

        // 管理员登录信息
        $token = $data['token'] ?? "";
        if (!$token) {
            Gateway::sendToClient($client_id, self::toJson([
                'type' => 'error',
                'msg' => '登录过期不能为空',
            ]));
            return;
        }

        $checkToken = (new AdminResult())->check_token($token, '*');
        if ($checkToken['code'] != 0) {
            Gateway::sendToClient($client_id, self::toJson([
                'type' => 'error',
                'msg' => '登录过期',
            ]));
            return;
        }

        $admin = $checkToken['data'];
        $kefu_id = strval($data['kefu_id'] ?? 0);

        Gateway::bindUid($client_id, $kefu_id);
        bs_log(Gateway::getUidByClientId($client_id), 'kefuUid', 'worker.log');

        $_SESSION['chat_user'] = [
            'admin_id' => $admin['admin_id'],
            'to_id' => $targetUser['id'],
            'user_id' => $kefu_id,
            'username' => '客服' . $kefu_id,
            'avatar' => 'https://source.alipay168.cn/skushop/d971248a1565ebf807b6454e6f818916.png',
        ];
        bs_log($_SESSION['chat_user'], '客服登录信息', 'worker.log');

        bs_log(Gateway::$registerAddress, '注册地址', 'worker.log');
        Gateway::sendToClient($client_id, self::toJson([
            'type' => 'login',
            'admin_id' => $admin['admin_id'],
            'client_id' => $client_id, // 修正此处的变量名
            'to_id' => $targetUser['id'],
            'user_id' => $kefu_id,
            'is_online' => Gateway::isUidOnline($kefu_id),
            'is_online1' => Gateway::isUidOnline($targetUser['id']),
            'username' => '客服' . $kefu_id,
            'avatar' => 'https://source.alipay168.cn/skushop/d971248a1565ebf807b6454e6f818916.png',
        ]));
    }

    //后台监听信息
    private static function handleListenMsg($client_id, $data)
    {
        // 管理员登录信息
        $token = $data['token'] ?? "";
        if (!$token) {
            Gateway::sendToClient($client_id, self::toJson([
                'type' => 'error',
                'msg' => '登录过期不能为空',
            ]));
            return;
        }

        $checkToken = (new AdminResult())->check_token($token, '*');
        if ($checkToken['code'] != 0) {
            Gateway::sendToClient($client_id, self::toJson([
                'type' => 'error',
                'msg' => '登录过期',
            ]));
            return;
        }

        $admin = $checkToken['data'];
        //Gateway::bindUid($client_id, $admin['admin_id']);
        //加入组
        Gateway::joinGroup($client_id, 'admin_msg_group');

        //发送消息,todo 在线状态
        /*Gateway::sendToUid($admin['admin_id'], self::toJson([
            'msg_type' => 'notify',
            'title' => '登录成功',
            'content' => '登录成功',
            'duration' => 1000,
            'notify_type' => 'success',
            'link' => ''
        ]));*/
    }

    /**
     * 处理用户登录逻辑
     * @param string $client_id 客户端ID
     * @param array $data 登录数据
     */
    private static function handleLogin($client_id, $data)
    {
        echo '登录：' . $client_id, PHP_EOL;

        $token = $data['token'] ?? "";
        if (!$token) {
            Gateway::sendToClient($client_id, self::toJson([
                'type' => 'error',
                'msg' => 'token不能为空',
            ]));
            return;
        }

        $userDecode = (new UserResult())->get_token_user($token, 'username,user_code,avatar,user_id');
        $user = $userDecode['code'] === 0 ? $userDecode['data'] : [];
        if (!$user) {
            Gateway::sendToClient($client_id, self::toJson([
                'type' => 'error',
                'msg' => 'token已失效',
            ]));
            return;
        }

        bs_log($user, '登录用户信息', 'worker.log');

        $targetUser = $data['targetUser'] ?? [];
        if (!$targetUser) {
            Gateway::sendToClient($client_id, self::toJson([
                'type' => 'error',
                'msg' => 'target_user不能为空',
            ]));
            return;
        }

        $to_id = $targetUser['id'] ?? '';

        // 绑定用户
        Gateway::bindUid($client_id, $user['user_id']);
        $user['to_id'] = $to_id;

        // 记录用户信息
        $_SESSION['chat_user'] = $user;
        Gateway::sendToClient($client_id, self::toJson([
            'type' => 'login',
            'user' => $user
        ]));
    }

    /**
     * 将数据转换为JSON字符串
     * @param mixed $data 要转换的数据
     * @return string JSON字符串
     */
    private static function toJson($data)
    {
        return json_encode($data, JSON_UNESCAPED_UNICODE);
    }

    /**
     * 当客户端断开连接时执行的操作
     * @param string $client_id 客户端ID
     */
    public static function onClose($client_id)
    {
        bs_log($client_id, 'onClose', 'worker.log');
        bs_log($_SESSION['chat_user'], 'onClose-用户', 'worker.log');

        if ($_SESSION['chat_user']) {
            unset($_SESSION['chat_user']);
        }
    }
}
